package com.aorise.service.bayonet.impl;

import com.aorise.exception.DataValidationException;
import com.aorise.exception.SystemException;
import com.aorise.mapper.bayonet.BayonetCameraMapper;
import com.aorise.mapper.bayonet.BayonetMapper;
import com.aorise.model.bayonet.*;
import com.aorise.service.bayonet.BayonetCameraService;
import com.aorise.utils.*;
import com.aorise.utils.excel.ExcelUtil;
import com.aorise.utils.excel.ImportExcel;
import com.aorise.utils.json.InnerResult;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @Auther: zhouhao
 * @Date: 2019/6/26
 * @Description:
 */
@Service
public class BayonetCameraServiceImpl implements BayonetCameraService{

    @Autowired
    BayonetCameraMapper bayonetCameraMapper;

    @Autowired
    BayonetMapper bayonetMapper;

    /**
     * 卡口设备分页列表
     * @param bayonetCameraPageVO 条件
     * @return
     */
    @Override
    public Page getBayonetCameraByPage(BayonetCameraPageVO bayonetCameraPageVO) {

        Page page = new Page();
        String pageNum = bayonetCameraPageVO.getPageNum();
        String pageSize = bayonetCameraPageVO.getPageSize();
        pageSize = StringUtils.isBlank(pageSize) ? "10" : pageSize;
        pageNum = StringUtils.isBlank(pageNum) ? "1" : pageNum;
        page.setCurrentPage(Long.valueOf(pageNum));
        page.setEveryPage(Long.valueOf(pageSize));
        Map<String, Object> map = Maps.newHashMap();
        map.put("bayonetCamera", bayonetCameraPageVO);
        map.put("state", ConstDefine.STATE_ABLE);
        long count = bayonetCameraMapper.getBayonetCameraCount(map);
        if (count > 0) {
            page.setTotalCount(count);
            page.setTotalPage(count, page.getEveryPage());
            if (page.getCurrentPage() > 0 && page.getEveryPage() > 0) {
                map.put("beginIndex", page.getBeginIndex());
                map.put("endinIndex", page.getEndinIndex());
                /**查询分页条数*/
                page.setList(bayonetCameraMapper.getBayonetCameraByPage(map));
            }
        } else {
            page.setTotalCount(0L);
        }
        return page;
    }

    /**
     * 添加卡口设备
     * @param bayonetCamera  添加信息
     * @return
     */
    @Override
    public boolean addBayonetCamera(BayonetCameraModel bayonetCamera) {
        Map map =Maps.newHashMap();
        map.put("state",ConstDefine.STATE_ABLE);
        map.put("caNumber",bayonetCamera.getCaNumber());
        BayonetCameraModel camera =bayonetCameraMapper.selectBayonetCamerByCaNumber(map);
        if(camera != null){
            throw new SystemException("设备编码已存在,无法保存");
        }
        Integer loginId = getLoginUser().getId();
        bayonetCamera.setOnline( bayonetCamera.getOnline() ==null?ConstDefine.CAMERA_ONLINE:bayonetCamera.getOnline() );
        bayonetCamera.setState(ConstDefine.STATE_ABLE);
        bayonetCamera.setCreateUser(loginId);
        bayonetCamera.setEditUser(loginId);
        List<BayonetCameraModel> bayonetCameras = Lists.newArrayList();
        bayonetCameras.add(bayonetCamera);
        return getBoolean(bayonetCameraMapper.addBayonetCamera(bayonetCameras));
    }

    /**
     * 卡口设备详情
     * @param bayonetCameraID
     * @return
     */
    @Override
    public BayonetCameraVo getBayonetCameraInfo(Integer bayonetCameraID) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("bayonetCameraID", bayonetCameraID);
        map.put("state", ConstDefine.STATE_ABLE);
        return bayonetCameraMapper.getBayonetCameraInfo(map);
    }

    /**
     * 修改卡口设备信息
     * @param bayonetCamera
     * @return
     */
    @Override
    public boolean upBayonetCamera(BayonetCameraModel bayonetCamera) {
        Map map =Maps.newHashMap();
        map.put("state",ConstDefine.STATE_ABLE);
        map.put("caNumber",bayonetCamera.getCaNumber());
        BayonetCameraModel camera =bayonetCameraMapper.selectBayonetCamerByCaNumber(map);
        if(camera != null && (camera.getId() !=bayonetCamera.getId())){
            throw new SystemException("设备编码已存在,无法保存");
        }
        bayonetCamera.setState(ConstDefine.STATE_ABLE);
        bayonetCamera.setEditUser(getLoginUser().getId());
        return getBoolean(bayonetCameraMapper.upBayonetCamera(bayonetCamera));
    }

    /**
     * 导出卡口设备信息
     * @param bayonetCameraPageVO   条件
     * @param response
     */
    @Override
    public void exportBayonetCamera(BayonetCameraPageVO bayonetCameraPageVO, HttpServletResponse response) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("bayonetCamera", bayonetCameraPageVO);
        map.put("state", ConstDefine.STATE_ABLE);
        List<LinkedHashMap<String,String>> bayonetCamera = bayonetCameraMapper.exportBayonetCamera(map);
        /**导出Excel*/
        List<String[]> dataList = Lists.newArrayList();
        LinkedHashMap linkedHashMap =null;
        int j =0;
        for(int i =0; i<bayonetCamera.size();i++){
            linkedHashMap = bayonetCamera.get(i);
            String[] dataString = new String[linkedHashMap.size()];
            Iterator iterator = linkedHashMap.entrySet().iterator();
            j =0;
            while (iterator.hasNext()){
                Map.Entry next = (Map.Entry) iterator.next();
                if(j == 3){
                    dataString[j] =getChinese((int)next.getValue(),"caType");
                }else if(j == 9){
                    dataString[j] =getChinese((int)next.getValue(),"online");
                }
                else {
                    dataString[j] =String.valueOf( next.getValue());
                }
                j++;
            }
            dataList.add(dataString);
        }
        ExcelUtil.writeExcel(dataList, null,11, 3, "卡口设备信息","bayonetCamera.xlsx", response);
    }

    /**
     * 导入卡口设备信息
     * @param excelFile
     */
    @Override
    public InnerResult<String> importBayonetCamera(MultipartFile excelFile) {

        List<ArrayList<String>> dataList = Lists.newArrayList();
        List<BayonetCameraModel> bayonetCameras =Lists.newArrayList();
        try {
            dataList = new ImportExcel().readExcelContent(excelFile.getInputStream());
            Integer loginUserId = getLoginUser().getId();

            /**验证每列数据格式*/
            String errMsg = checkExcelData(dataList);
            if (!errMsg.equals("")) {
                /**数据格式有误*/
                return new InnerResult<String>(false, errMsg);
            }

            for(int i =0;i<dataList.size();i++) {
//                当前数据
                List<String> date = dataList.get(i);
                //卡口设备第一列不需要
                BayonetCameraModel bayonetCamera = BayonetCameraModel.builder().bayoneId(date.get(1)).caType(BayonetCameraEnum.getId(date.get(3)))
                        .caName(date.get(4)).unitType(date.get(5)).caNumber(date.get(6)).monitorLane(date.get(7)).shootLane(date.get(8))
                        .online(OnlineEnum.getId( date.get(9))).ip(date.get(10)).state(ConstDefine.STATE_ABLE).createUser(loginUserId).editUser(loginUserId).build();
                bayonetCameras.add(bayonetCamera);
            }
            if(CollectionUtils.isNotEmpty(bayonetCameras)){
                bayonetCameraMapper.addBayonetCameraImp(bayonetCameras);
            }
            return new InnerResult<String>(true, "成功导入"+ dataList.size() +"条数据!");
        } catch (Exception e) {
            e.printStackTrace();
            throw new DataValidationException("请使用正规的模板进行插入数据");
        }
    }

    /**
     * 数据校验
     * @param dataList
     * @return
     */
    private String checkExcelData(List<ArrayList<String>> dataList) {

        /**数据效验*/
        DataValidation dataValidation = new DataValidation();
        List<String> errStr = Lists.newArrayList();;
        System.out.println();
        ArrayList<String> rowList = Lists.newArrayList();
        List caNumberList = Lists.newArrayList();
        Map map = Maps.newHashMap();
        map.put("state", ConstDefine.STATE_ABLE);
        Integer group =null;
        BayonetModel bayonet =null;
        for(int i =0;i<dataList.size();i++){
            rowList =dataList.get(i);
            for(int j =0;j<rowList.size();j++){

                switch (j){
                    case 0:
                        if(StringUtils.isNotBlank(rowList.get(j).toString()) ){
                            map.put("gName",rowList.get(j).toString());
                            group =bayonetMapper.selectGroupByGName(map);
                            if(group ==null){
                                errStr.add(  "第" +(i+3)+"行" + (j + 1) + "列,卡口所属分组类型不存在");
                            }
                        }
                        break;
                    case 1:
                        map.put("baNumber",rowList.get(1));
                        bayonet =bayonetMapper.selectBayonetByBaNumber(map);
                        if(bayonet == null){
                            errStr.add(  "第" +(i+3)+"行" + (j + 1) + "列,所属卡口编码不存在");
                        }
                        if(StringUtils.isBlank(rowList.get(j).toString()) ){
                            errStr.add(  "第" +(i+3)+"行" + (j + 1) + "列,所属卡口编码为必填项");
                        }else if (!dataValidation.chkLength(rowList.get(j).toString().trim(), 0, 20)) {
                            errStr.add( "第" +(i+3)+"行" + (j + 1) + "列,所属卡口编码数据格式有误");
                        }
                    case 2:
                        if(StringUtils.isBlank(rowList.get(j).toString())){
                            errStr.add( "第" +(i+3)+"行" + (j + 1) + "列,卡口名称为必填项");
                        }else if (StringUtils.isNotBlank(rowList.get(j).toString()) &&!dataValidation.chkLength(rowList.get(j).toString().trim(), 0, 60)) {
                            errStr.add( "第" +(i+3)+"行" + (j + 1) + "列,卡口名称数据格式有误");
                        }
                        break;
                    case 3: // 1 3 456 789 10
                        if(StringUtils.isBlank(rowList.get(j).toString()) ){
                            errStr.add(  "第" +(i+3)+"行" + (j + 1) + "列,设备类型为必填项");
                        }else if (!BayonetCameraEnum.isHas(rowList.get(j).toString())) {
                            errStr.add(  "第" +(i+3)+"行" + (j + 1) + "列,设备类型不存在");
                        }
                        break;
                    case 4:
                        if(StringUtils.isBlank(rowList.get(j).toString()) ){
                            errStr.add(  "第" +(i+3)+"行" + (j + 1) + "列,设备名称为必填项");
                        }
                        if (StringUtils.isNotBlank(rowList.get(j).toString()) &&!dataValidation.chkLength(rowList.get(j).toString().trim(), 0, 60)) {
                            errStr.add( "第" +(i+3)+"行" + (j + 1) + "列,设备名称格式有误");
                        }
                        break;
                    case 5:
                        if (StringUtils.isNotBlank(rowList.get(j).toString()) &&!dataValidation.chkLength(rowList.get(j).toString().trim(), 0, 20)) {
                            errStr.add( "第" +(i+3)+"行" + (j + 1) + "列,设备型号格式有误");
                        }
                        break;
                    case 6:
                        if(StringUtils.isBlank(rowList.get(j).toString()) ){
                            errStr.add(  "第" +(i+3)+"行" + (j + 1) + "列,设备编码为必填项");
                        }
                        if (StringUtils.isNotBlank(rowList.get(j).toString()) &&!dataValidation.chkLength(rowList.get(j).toString().trim(), 0, 20)) {
                            errStr.add( "第" +(i+3)+"行" + (j + 1) + "列,设备编码格式有误");
                        }
                        map.put("caNumber",rowList.get(j).toString());
                        BayonetCameraModel bayonetCamera =bayonetCameraMapper.selectBayonetCamerByCaNumber(map);
                        if (bayonetCamera != null) {
                            errStr.add( "第" + ( i+ 3) + "行"+ (j + 1) +"列,设备编码已存在!");
                        } else {
//                            保存每一行的设备编码，用来判断是否有重复
                            caNumberList.add(rowList.get(j));
                        }
                        break;
                    case 7:
                    case 8:
                        if (StringUtils.isNotBlank(rowList.get(j).toString()) && !dataValidation.chekeIdNo(subZeroAndDot(rowList.get(j).toString().trim()))) {
                            errStr.add( "第" +(i+3)+"行" + (j + 1) + "列,车道请存入数字,格式为：1,2,3");
                        }
                        if (StringUtils.isNotBlank(rowList.get(j).toString()) &&!dataValidation.chkLength(rowList.get(j).toString().trim(), 0, 50)) {
                            errStr.add( "第" +(i+3)+"行" + (j + 1) + "列,车道格式有误");
                        }
                        break;
                    case 9:
                        if (StringUtils.isNotBlank(rowList.get(j).toString())&& !OnlineEnum.isHas(rowList.get(j).toString()) ) {
                            errStr.add(  "第" +(i+3)+"行" + (j + 1) + "列,连接状态不存在");
                        }
                        break;
                    case 10:
                        /**IP地址*/
                        if (!rowList.get(j).toString().trim().equals("")) {
                            if (!dataValidation.chekeIP4(rowList.get(j).toString().trim())) {
                                errStr.add(  "第" +(i+3)+"行" + (j + 1) + "列,IP地址不存在");
                            }
                        }
                        break;
                }
            }
        }
        /**判断设备编码是否有重复*/
        if (caNumberList.size() > 0) {
            HashSet set = new HashSet<>(caNumberList);
            if (set.size() != caNumberList.size()) {
                errStr.add( "文件设备编码有重复!");
            }
        }
        return String.join(";",errStr);
    }

    /**
     * 获取常量值的中文
     *
     * @param num  常量值
     * @param type 常量值类型
     * @return
     */
    private String getChinese(Integer num, String type) {
        switch (type) {
            case "caType":
                return BayonetCameraEnum.getValue(num);
            case "online":
                if (num == ConstDefine.CAMERA_ONLINE) {
                    return "在线";
                } else if (num == ConstDefine.CAMERA_OFFLINE) {
                    return "离线";
                }
        }
        return "";
    }

    /**
     * 使用java正则表达式去掉多余的.与0
     * @param s
     * @return
     */
    private String subZeroAndDot(String s) {
        if (s.indexOf(".") > 0) {
            s = s.replaceAll("0+?$", "");//去掉多余的0
            s = s.replaceAll("[.]$", "");//如最后一位是.则去掉
        }
        return s;
    }
}
